using System;
using GameFrameworkLibraly.BaseObjects;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace GameFrameworkLibraly.Controls
{
    public class ProgressBarControl:Control
    {
        /// <summary>
        /// Texture that will be drawn as a progress
        /// </summary>
        public Texture2D ForeTexture { get; set; }

        /// <summary>
        /// Background texture
        /// </summary>
        public Texture2D BackTexture { get; set; }

        private int _minValue;
        private int _maxValue = 100;
        private int _progress;

        /// <summary>
        /// Occures when progress has been changed
        /// </summary>
        public event EventHandler ProgressChanged;

        /// <summary>
        /// Creates a new instance of Progress bar
        /// </summary>
        /// <param name="game">Current game</param>
        /// <param name="destinationRectangle">Defines rectangle where the control must be drawn</param>
        /// <param name="foreTexture">Texture that will be drawn as a progress</param>
        /// <param name="backTexture">Background texture</param>
        public ProgressBarControl(MyGame game, Rectangle destinationRectangle, Texture2D foreTexture, Texture2D backTexture):base(game)
        {
            DestinationRectangle = destinationRectangle;
            ForeTexture = foreTexture;
            BackTexture = backTexture;
        }
        
        /// <summary>
        /// Minimal value for this Progress Bar (0 as default )
        /// </summary>
        public int MinValue
        {
            get { return _minValue; }
            set
            {
                if (value > MaxValue)
                    throw new ArgumentException("Min value must be less than MaxValue");
                _minValue = value;
            }
        }

        /// <summary>
        /// Maximal value for this Progress Bar (100 as default)
        /// </summary>
        public int MaxValue
        {
            get { return _maxValue; }
            set
            {
                if (value < MinValue)
                    throw new ArgumentException("Min value must be more than MinValue");
                _maxValue = value;
            }
        }

        /// <summary>
        /// Current value for this Progress Bar (must be between minimum and maximum)
        /// </summary>
        public int Progress
        {
            get { return _progress; }
            set
            {
                if (value >= MinValue && value <= MaxValue)
                    _progress = value;
                else
                    _progress = MinValue;
                InvokeProgressChanged(EventArgs.Empty);
            }
        }

        #region Control

        /// <summary>
        /// Draws the control
        /// </summary>
        /// <param name="spriteBatch"></param>
        public override void Draw(SpriteBatch spriteBatch)
        {
            if(!Visible)
                return;
            if (BackgroundTexture != null)
                spriteBatch.Draw(BackgroundTexture, DestinationRectangle, BackColorFilter);
            DrawBackground(spriteBatch);
            DrawForeGround(spriteBatch);
        }

        /// <summary>
        /// Updates state of the control
        /// </summary>
        /// <param name="gameTime"></param>
        public override void Update(GameTime gameTime)
        {
        }

        #endregion


        protected void InvokeProgressChanged(EventArgs e)
        {
            EventHandler handler = ProgressChanged;
            if (handler != null) handler(this, e);
        }

        //TODO: Make 2 next methods not so heavy

        /// <summary>
        /// Draws foreground that depends on progress
        /// </summary>
        /// <param name="spriteBatch"></param>
        protected virtual void DrawForeGround(SpriteBatch spriteBatch)
        {
            float foreTexturesCount = ((DestinationRectangle.Width / 100.0f * Progress)) / ForeTexture.Width;

            int integerPart = (int)foreTexturesCount;
            float fractionalPart = foreTexturesCount - integerPart;

            for (int i = 0; i < integerPart; i++)
            {
                Rectangle rectangle = new Rectangle(DestinationRectangle.X + i * ForeTexture.Width, DestinationRectangle.Y, ForeTexture.Width, DestinationRectangle.Height);
                spriteBatch.Draw(ForeTexture, rectangle, ForeColor);
            }


            Rectangle rectangle2 = new Rectangle(DestinationRectangle.X + integerPart * ForeTexture.Width, DestinationRectangle.Y, (int)(ForeTexture.Width * fractionalPart), DestinationRectangle.Height);
            spriteBatch.Draw(ForeTexture, rectangle2, new Rectangle(0, 0, (int)(ForeTexture.Width * fractionalPart), ForeTexture.Height), ForeColor);
        }

        /// <summary>
        /// Draws background
        /// </summary>
        /// <param name="spriteBatch"></param>
        protected virtual void DrawBackground(SpriteBatch spriteBatch)
        {
            int backTexturesCount = DestinationRectangle.Width / BackTexture.Width + 1;
            for (int i = 0; i < backTexturesCount; i++)
            {
                Rectangle rectangle = new Rectangle(DestinationRectangle.X + i * BackTexture.Width, DestinationRectangle.Y, BackTexture.Width, DestinationRectangle.Height);
                spriteBatch.Draw(BackTexture, rectangle, ForeColor);
            }
        }
    }
}
